using System.Runtime.InteropServices;
using System.Threading;

namespace VirtualKeyboard.Service.Commands
{
    public interface IKeyBoardHook
    {
        void PressKey(Keys keyCode);
        void PressKey(Keys[] keyCode);
    }

    public sealed class KeyBoardHook : IKeyBoardHook
    {
        private static readonly KeyBoardHook instance = new KeyBoardHook();

        public static KeyBoardHook Instance
        {
            get { return instance; }
        }

        private KeyBoardHook()
        {
            
        }

        private enum KeyBoard
        {
            KeyDown = 0x0001,
            KeyUp = 0x0002
        }

        public void PressKey(Keys keyCode)
        {
            PressKey(new[] { keyCode });
        }

        public void PressKey(Keys[] keyCodes)
        {
            if (keyCodes == null || keyCodes.Length == 0) return;

            int length = keyCodes.Length;
            for (int i = 0; i < length; i++)
            {
                PutDownKey(keyCodes[i]);
            }
            Thread.SpinWait(5000);
            for (int i = length - 1; i >= 0; i--)
            {
                ReceiveKey(keyCodes[i]);
            }
        }

        private static void PutDownKey(Keys keyCode)
        {
            KeyboardEvent((byte)keyCode, 0, KeyBoard.KeyDown, 0);
        }

        private static void ReceiveKey(Keys keyCode)
        {
            KeyboardEvent((byte)keyCode, 0, KeyBoard.KeyUp, 0);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "keybd_event")]
        private static extern void KeyboardEvent(
            byte bVk,
            byte bScan,
            KeyBoard dwFlags,
            int dwExtraInfo
            );
    }
}